# Python imports
from functools import wraps

# Django imports
from django.conf import settings
from django.core.cache import cache

# Third party imports
from rest_framework.response import Response


def generate_cache_key(custom_path, auth_header=None):
    """Generate a cache key with the given params"""
    if auth_header:
        key_data = f"{custom_path}:{auth_header}"
    else:
        key_data = custom_path
    return key_data


def cache_response(timeout=60 * 60, path=None, user=True):
    """decorator to create cache per user"""

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(instance, request, *args, **kwargs):
            # Function to generate cache key
            auth_header = (
                None
                if request.user.is_anonymous
                else str(request.user.id) if user else None
            )
            custom_path = path if path is not None else request.get_full_path()
            key = generate_cache_key(custom_path, auth_header)
            cached_result = cache.get(key)
            if cached_result is not None:
                return Response(
                    cached_result["data"], status=cached_result["status"]
                )
            response = view_func(instance, request, *args, **kwargs)

            if response.status_code == 200 and not settings.DEBUG:
                cache.set(
                    key,
                    {"data": response.data, "status": response.status_code},
                    timeout,
                )

            return response

        return _wrapped_view

    return decorator


def invalidate_cache(path=None, url_params=False, user=True):
    """invalidate cache per user"""

    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(instance, request, *args, **kwargs):
            # Invalidate cache before executing the view function
            if url_params:
                path_with_values = path
                for key, value in kwargs.items():
                    path_with_values = path_with_values.replace(
                        f":{key}", str(value)
                    )

                custom_path = path_with_values
            else:
                custom_path = (
                    path if path is not None else request.get_full_path()
                )

            auth_header = (
                None
                if request.user.is_anonymous
                else str(request.user.id) if user else None
            )
            key = generate_cache_key(custom_path, auth_header)
            cache.delete(key)
            # Execute the view function
            return view_func(instance, request, *args, **kwargs)

        return _wrapped_view

    return decorator
